﻿using Caliburn.Micro;
using MCPlatform.Builder.WorkStation.StationEvents;
using MCPlatform.Builder.WorkStation.StationEvents.Cutting;
using MCPlatform.Builder.WorkStation.StationEvents.Unload;
using MCPlatform.Components.Utilities;
using MCPlatform.Models;
using MCPlatform.MotionLib.Base;
using MCPlatform.MotionLib.Base.AssitantClass;
using MCPlatform.MotionLib.Base.AssitantClass.Exceptions;
using MCPlatform.MotionLib.Base.Environment;
using MCPlatform.UI.Controls.Models;
using MCPlatform.ViewModels.Product;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;

namespace MCPlatform.Builder.WorkStation
{
    public class UnloadStation : WorkStationBase,IHandle<CuttingToUnloadEvent>
    {
        #region Properties

        public   IMotion UnloadXAxis { get; set; }

        public IMotion UnloadYAxis { get; set; }

        public IMotion UnloadZAxis { get; set; }

        public IValve Vacuum { get; set; }

        public PointSettingModel UnloadXWaitPos { get; set; }

        public PointSettingModel UnloadYWaitPos { get; set; }

        public PointSettingModel UnloadZWaitPos { get; set; }


        //public PointSettingModel UnloadXPickPos { get; set; }

        //public PointSettingModel UnloadYPickPos { get; set; }

        //public PointSettingModel UnloadZPickPos { get; set; }

        public PointSettingModel UnloadZPlacePos { get; set; }

        public PointSettingModel VacuumSuckTime { get; set; }

        public static int UnloadCount { get; set; }

        public ProductModel ProductModel { get; set; } = ProductInfo.GetProductInfo() ?? new ProductModel();

        public uint UnloadNumber
        {
            get => _UnloadNumber;
            set
            {
                Set(ref _UnloadNumber, value);
                UnloadNumberChangedEvent?.Invoke(value);

            }


        }
        public uint _UnloadNumber = 0;


        #endregion Properties

        #region Fields

        private bool _isRunning;


       

        #endregion

        #region Event declare

        public event System.Action<uint>? UnloadNumberChangedEvent;


        public event System.Action? UnloadFullEvent;

        public event System.Action? UnloadEmptyEvent;

        #endregion

        #region CTOR
        private static UnloadStation? instance;

        private static readonly object lockObject = new object();

        private UnloadStation()
        {
            //1.映射基本信息
            WorkStationModel = WorkStation.Instance.WorkStationDic[3];


            UnloadXAxis = AxisModels[0].MotionEntity!;
            UnloadYAxis = AxisModels[1].MotionEntity!;
            UnloadZAxis = AxisModels[2].MotionEntity!;


            Vacuum = CylinderModels[0].ValveEntity!;

            UnloadXWaitPos = PointSettingModels[0];

            UnloadYWaitPos = PointSettingModels[1];

            UnloadZWaitPos = PointSettingModels[2];

            //UnloadXPickPos = PointSettingModels[3];

            //UnloadYPickPos = PointSettingModels[4];

            //UnloadZPickPos = PointSettingModels[5];

            UnloadZPlacePos = PointSettingModels[3];

            VacuumSuckTime = PointSettingModels[4];

            //UnloadUpOffsetDis = PointSettingModels[3];


            //ChangeTrayUnloadUpOffsetDis = PointSettingModels[4];

            //TakeOutTrayAndReceptPos = PointSettingModels[5];

        }

        public static UnloadStation Instance
        {
            get
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new UnloadStation();
                    }
                    return instance;
                }
            }
        }

        public override void RegisterEvent()
        {
            ProductViewModel.SaveEvent += ProductViewModel_SaveEvent;
        }

        private void ProductViewModel_SaveEvent(ProductModel model)
        {
            ProductModel = model;
        }


        #endregion CTOR

        #region Methods

        public override async Task<bool> IsSaftyToMove()
        {
           
            await Task.Delay(1);
            return true;
        }

        public bool IsSaftyToXMove()
        {
            if ( Math.Abs(UnloadZAxis.ActualPosition - UnloadZWaitPos.Parameter) > 3)
            {
                throw new MyAxisException("下料Z轴不在安全位置移动！");
                // return false;
            }
            
            return true;
        }

        public override async Task Initial()
        {

            try
            {
               
                await ResetSignal();

                await Task.Run(async () =>
                {


                    IsReady = false;

                    IsDone = false;


                    //0.有料位有信号不能回原
                    await IsSaftyToMove();
                    //1.全部轴使能
                    SetAllAxisEnable();

                    //2.全部气缸回原位
                    await SetAllValvesBasing();

                    //3.轴回原
                    await HomeAsync(UnloadZAxis);
                    await HomeAsync(UnloadYAxis);
                    await HomeAsync(UnloadXAxis);

                    //4.轴去等待位
                    await AbsMoveAsync(UnloadZAxis, UnloadZWaitPos);
                    await AbsMoveAsync(UnloadYAxis, UnloadYWaitPos);
                    await AbsMoveAsync(UnloadXAxis, UnloadXWaitPos);


                    //6.初始化完成
                    LogModel.LogInfo = "初始化完成！";
                    LogModel.Status = Shared.Enums.WorkStationStatus.Idle;


                    //5.触发准备好信号给到上料
                    ReadyEventTrigger(this);

                }, cancellationToken);
            }
            catch (System.Exception)
            {
                throw;
            }

        }

      
        public override async Task DryRun()
        {
            try
            {
               
                await Task.Run(async () =>
                {
                    if (_isRunning)
                    {
                        return;
                    }
                    LogModel.LogInfo = "开始运行";
                    LogModel.Status = Shared.Enums.WorkStationStatus.Execute;
                    _isRunning = true;

                    int unloadNumber = (int)ProductModel.UnloadProductNumberOneTime;

                    int productNumber = (int)ProductModel.CuttingProductNumberOneTime;

                    int times = productNumber / unloadNumber;

                    // await UnloadDut();

                    //每一次取料，先判断是一次取几个产品，如果是2个，就用次数*间隔

                    for (int i = 0; i < times; i++)
                    {
                        await UnloadDut(i * unloadNumber);
                    }




                    //3.发送Done信号给切割模块
                    DoneEventTrigger(this,new UnloadToCuttingEvent() { MessageType = MessageType.NotifyDone});

                    _isRunning = false;

                }, cancellationToken);

            }
            catch (Exception e)
            {
                Logger.Error(e,"下料工站");
                throw;
            }
            finally { _isRunning = false; }
        }

     



        public override async Task Execute()
        {
            
            await Task.Delay(1000);
        }

        public override Task Clear(bool isClear)
        {
           
            return Task.CompletedTask;
        }
        

        private async Task UnloadDut(int times = 0)
        {
            try
            {
                IsSaftyToXMove();

                var productInfo = ProductModel;

                if (productInfo is null)
                {
                    StopTrigger("产品信息丢失！");
                    return;
                }

                //1.Z到等待位
                await AbsMoveAsync(UnloadZAxis, UnloadZWaitPos);

                //2. XY到等待位
                IMotion[] motions = new IMotion[] { UnloadXAxis, UnloadYAxis };
               

                //判断是第几次切割，要移动相应的距离
                double xOffset = times * (productInfo.PatternSpace + productInfo.Space + productInfo.CuttingLength + productInfo.KnifeCompensate);


                PointSettingModel newXPick = new PointSettingModel() { Parameter = productInfo.XAxisUnloadStartPos + xOffset };


                //3. XY到取料位
                await MultiAbsMoveAsync(motions, newXPick, new PointSettingModel() { Parameter = productInfo.YAxisUnloadStartPos});

                //3.5.检查下料数量是否到达最大值
               // int unloadMaxNumber = ProductInfo.GetUnloadMaxNumber();
                if (_UnloadNumber > productInfo.UnloadMaxNumber)
                {
                    UnloadFullEvent?.Invoke();
                    var result = MessageBox.Show("码垛数量已达最大值，请更换码垛车！更换完成再按确定！", "提示", MessageBoxButton.OK);
                    _UnloadNumber = 0;
                    UnloadEmptyEvent?.Invoke();
                }

                //4.Z到取料位
                await AbsMoveAsync(UnloadZAxis, productInfo.ZAxisUnloadStartPos);

                //5.打开吸盘
                await WorkingAsync(Vacuum);

                await Task.Delay((int)VacuumSuckTime.Parameter);

                //6.Z到等待位
                await AbsMoveAsync(UnloadZAxis, UnloadZWaitPos);

                IsSaftyToXMove();
                //7.XY到码垛位，即等待位
                await MultiAbsMoveAsync(motions, UnloadXWaitPos, UnloadYWaitPos);

                //8.Z到码垛位

               
                PointSettingModel placeZPos = new PointSettingModel()
                {
                    ControlName = UnloadZPlacePos.ControlName,
                    Parameter = UnloadZPlacePos.Parameter - productInfo.Thickness * (_UnloadNumber/ productInfo.UnloadProductNumberOneTime)
                };//1mm 一张皮革的厚度
                await AbsMoveAsync(UnloadZAxis, placeZPos);

                //9.松开吸盘
                await BasingAsync(Vacuum);

                //10.Z到等待位
                await AbsMoveAsync(UnloadZAxis, UnloadZWaitPos);
          
                UnloadCount = UnloadCount + (int)productInfo.UnloadProductNumberOneTime;
                UnloadNumber = UnloadNumber + productInfo.UnloadProductNumberOneTime;
            }
            catch (Exception)
            {

                throw;
            }
        }

       
        public override  async Task Test()
        {
            UnloadCount = UnloadCount + (int)ProductModel.UnloadProductNumberOneTime;
            UnloadNumber = UnloadNumber + ProductModel.UnloadProductNumberOneTime;
           
            IsReady = false;
            IsDone = !IsDone;

            //return Task.CompletedTask;
           
        }

        public override Task ResetSignal()
        {
            _UnloadNumber = 0;
            UnloadCount = 0;
            PauseEventSource.Set();
            SingleStepCompleteEvent.Set();
            
            return Task.CompletedTask;
        }

        public override void StationStop()
        {
            ;
        }


        #endregion Methods

        #region Event Handlers
        public async Task HandleAsync(CuttingToUnloadEvent message, CancellationToken cancellationToken)
        {
            try
            {
                if (IsDoneNotify(message))
                {
                    Send(new CuttingToLoadEvent() { MessageType = MessageType.ResetDone });
                    await DryRun();
                }
               
            }
            catch (Exception)
            {
                StopTrigger(isSetAbortedStatus: false);
                return;
               // throw;
            }
           
        }


        #endregion Event Handlers

        #region Utility

      

        #endregion

    }
}